package org.jeecg.modules.wlhy.report;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.enums.ReportPlatformEnum;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.LngLonUtil;
import org.jeecg.modules.third.amap.dto.GpsDTO;
import org.jeecg.modules.third.amap.dto.MapDirectionDTO;
import org.jeecg.modules.third.amap.dto.RegeoDTO;
import org.jeecg.modules.third.amap.service.AmapService;
import org.jeecg.modules.third.jg.report.freight.information.constant.OrdosReportConstant;
import org.jeecg.modules.third.jg.report.freight.information.constant.enums.AhUploadStatusEnum;
import org.jeecg.modules.third.jg.report.freight.information.constant.enums.PaymentMeansCodeEnum;
import org.jeecg.modules.third.jg.report.freight.information.constant.enums.ReportDocTypeEnum;
import org.jeecg.modules.third.jg.report.freight.information.dto.AppInfoDTO;
import org.jeecg.modules.third.jg.report.freight.information.dto.DriverDTO;
import org.jeecg.modules.third.jg.report.freight.information.dto.VehicleDTO;
import org.jeecg.modules.third.jg.report.freight.information.dto.financial.FinancialDTO;
import org.jeecg.modules.third.jg.report.freight.information.dto.financial.FinanciallistDTO;
import org.jeecg.modules.third.jg.report.freight.information.dto.shippingnote.ActualCarrierInfo;
import org.jeecg.modules.third.jg.report.freight.information.dto.shippingnote.AhShippingNoteDTO;
import org.jeecg.modules.third.jg.report.freight.information.dto.shippingnote.ShippingNoteDTO;
import org.jeecg.modules.third.jg.report.freight.information.model.R;
import org.jeecg.modules.third.jg.report.freight.information.ordosdto.*;
import org.jeecg.modules.third.jg.report.freight.information.service.AhReportPlatformService;
import org.jeecg.modules.third.jg.report.freight.information.service.OrdosReportPlatformService;
import org.jeecg.modules.third.oapi.alct56.dto.req.shippingnote.TracesInfoDTO;
import org.jeecg.modules.third.openapi.WaybillRouteService;
import org.jeecg.modules.wlhy.bill.entity.HyShippingNoteBill;
import org.jeecg.modules.wlhy.bill.service.IHyShippingNoteBillService;
import org.jeecg.modules.wlhy.company.entity.HyCompany;
import org.jeecg.modules.wlhy.company.entity.HyCompanyConfig;
import org.jeecg.modules.wlhy.company.service.IHyCompanyService;
import org.jeecg.modules.wlhy.customer.entity.HyCustomer;
import org.jeecg.modules.wlhy.customer.entity.HyCustomerCompany;
import org.jeecg.modules.wlhy.customer.service.IHyCustomerCompanyService;
import org.jeecg.modules.wlhy.customer.service.IHyCustomerService;
import org.jeecg.modules.wlhy.hyarea.service.IHyAreaService;
import org.jeecg.modules.wlhy.hydriver.entity.HyDriver;
import org.jeecg.modules.wlhy.hydriver.entity.HyDriverReport;
import org.jeecg.modules.wlhy.hydriver.service.IHyDriverReportService;
import org.jeecg.modules.wlhy.hydriver.service.IHyDriverService;
import org.jeecg.modules.wlhy.hydriverbank.entity.HyDriverBank;
import org.jeecg.modules.wlhy.hydriverbank.service.IHyDriverBankService;
import org.jeecg.modules.wlhy.hyvehicle.entity.HyVehicle;
import org.jeecg.modules.wlhy.hyvehicle.entity.HyVehicleReport;
import org.jeecg.modules.wlhy.hyvehicle.entity.HyVehicleType;
import org.jeecg.modules.wlhy.hyvehicle.service.IHyVehicleReportService;
import org.jeecg.modules.wlhy.hyvehicle.service.IHyVehicleService;
import org.jeecg.modules.wlhy.invoice.entity.HyInvoice;
import org.jeecg.modules.wlhy.invoice.service.IHyInvoiceService;
import org.jeecg.modules.wlhy.order.entity.HyOrder;
import org.jeecg.modules.wlhy.order.service.IHyOrderService;
import org.jeecg.modules.wlhy.report.impl.BaseReportService;
import org.jeecg.modules.wlhy.setting.service.IHySettingService;
import org.jeecg.modules.wlhy.shipping.constant.ShippingPayStatus;
import org.jeecg.modules.wlhy.shipping.constant.ShippingStatus;
import org.jeecg.modules.wlhy.shipping.entity.HyOrdosReport;
import org.jeecg.modules.wlhy.shipping.entity.HyShippingNote;
import org.jeecg.modules.wlhy.shipping.entity.PointDataListVO;
import org.jeecg.modules.wlhy.shipping.entity.WaybillRouteVO;
import org.jeecg.modules.wlhy.shipping.service.IHyOrdosReportService;
import org.jeecg.modules.wlhy.shipping.service.IHyShippingNoteService;
import org.jeecg.modules.wlhy.utils.HyCfgUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class OrdosReportService implements IReportService {
    @Resource
    private BaseReportService baseReportService;

    @Resource
    private IHyDriverService driverService;

    @Resource
    private IHyDriverBankService driverBankService;

    @Resource
    private IHyVehicleService vehicleService;

    @Resource
    private IHyCustomerService customerService;

    @Resource
    private IHyCustomerCompanyService customerCompanyService;

    @Resource
    private IHyAreaService hyAreaService;

    @Resource
    private IHyDriverReportService hyDriverReportService;

    @Resource
    private IHyVehicleReportService vehicleReportService;

    @Resource
    private IHyCompanyService companyService;

    @Resource
    private AmapService amapService;

    @Resource
    private IHyAreaService areaService;

    @Resource
    private IHyOrdosReportService hyOrdersReportService;

    @Resource
    private OrdosReportPlatformService ordosReportPlatformService;

    @Autowired
    private WaybillRouteService waybillRouteService;

    @Autowired
    private IHyShippingNoteService hyShippingNoteService;

    @Autowired
    private IHyShippingNoteBillService hyShippingNoteBillService;

    @Autowired
    private IHySettingService settingService;

    @Autowired
    private IHyOrderService orderService;

    @Autowired
    private IHyInvoiceService hyInvoiceService;

    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;

    @Value(value = "${jeecg.path.bank}")
    private String bankpath;

    @Value(value="${ordos-report-platform.staticUrl:}")
    private String staticUrl;

    @Override
    public ReportPlatformEnum getReportType() {
        return ReportPlatformEnum.REPORT_PLATFORM_ORDOS;
    }

    @Override
    public void checkReport() {
    }

    @Override
    public Result setReportInfo(HyCompanyConfig hyCompanyConfig) {
        return Result.ok("设置成功");
    }

    @Override
    public AppInfoDTO getAppInfo() {
        return null;
    }

    @Override
    public boolean report(HyShippingNote hyShippingNote) {
        return false;
    }

    @Override
    public Result reportShippingNote(HyShippingNote hyShippingNote) {
        return Result.OK();
    }

    @Override
    public Result reportCapitalFlow(HyShippingNote hyShippingNote) {
        return Result.OK();
    }


    /**
     * 平台司机上报
     *{
     * “drivercardBack”: “https://testcdn.groupring.cn/20230915/9172f429c079435680d2a596eb9b5d51.png“,
     * “drivercardDeadline”: “2023-10-10 10:00:00”,
     * “drivercardHome”: “https://testcdn.groupring.cn/20230915/5b1e627be5c743f0bc54ceed38dc7ec4.png“,
     * “drivingModel”: “A2”,
     * “idCardDeadline”: “2023-10-10 10:00:00”,
     * “idcardBack”: “https://testcdn.groupring.cn/20230915/216ed5f5aa0e4e4bbcf71cc71d59dfa4.png“,
     * “idcardCode”: “152630198911127910”,
     * “idcardFront”: “https://testcdn.groupring.cn/20230915/acb545f869fe47cf9fcd9361e22ded85.png“,
     * “mobile”: “15972588048”,
     * “name”: “白羽”,
     * “qualificationCode”: “123456789”,
     * “qualificationDeadline”: “2023-10-10 10:00:00”,
     * “qualificationUrl”: “”,
     * “remark”: “”
     * }
     * @param driverId
     * @return
     */
    @Override
    public Result reportDriver(String driverId, String companyId) {

        HyDriver hyDriverDb = driverService.getById(driverId);
        if (hyDriverDb == null) {
            return Result.error("未找到对应数据");
        }

        if (null == hyDriverDb.getIdcardExpiredDate()) {
            return Result.error("司机身份证有效期未填写");
        }

        if (null == hyDriverDb.getValidPeriodTo()) {
            return Result.error("司机驾驶证有效期未填写");
        }

        if (null == hyDriverDb.getQualificationCertificate()) {
            return Result.error("司机从业资格证号未填写");
        }

        if (null == hyDriverDb.getQualificationExpiredDate()) {
            return Result.error("司机从业资格证有效期未填写");
        }

        if (hyDriverDb.getIdcardExpiredDate().before(new Date())) {
            return Result.error("司机身份证已过期，请确认是否填写正确");
        }

        if (hyDriverDb.getValidPeriodTo().before(new Date())) {
            return Result.error("司机驾驶证已过期，请确认是否填写正确");
        }

        if (hyDriverDb.getQualificationExpiredDate().before(new Date())) {
            return Result.error("司机从业资格证已过期，请确认是否填写正确");
        }

        DriverReportDTO driverReportDTO = new DriverReportDTO();
        driverReportDTO.setName(hyDriverDb.getDriverName());
        driverReportDTO.setMobile(hyDriverDb.getTelephone());
        driverReportDTO.setIdcardCode(hyDriverDb.getIdcard());
        driverReportDTO.setIdcardFront(staticUrl + hyDriverDb.getIdcardImgBack());
        driverReportDTO.setIdcardBack(staticUrl + hyDriverDb.getIdcardImg());
        driverReportDTO.setDrivercardHome(staticUrl + hyDriverDb.getDriverImg());
        driverReportDTO.setDrivercardBack(staticUrl + hyDriverDb.getDriverImg2());
        driverReportDTO.setDrivingModel(hyDriverDb.getVehicleClass());
        driverReportDTO.setQualificationCode(hyDriverDb.getQualificationCertificate());
        driverReportDTO.setQualificationUrl(staticUrl + hyDriverDb.getQualificationImg());
        driverReportDTO.setQualificationDeadline(DateUtils.dateTimeToString(hyDriverDb.getQualificationExpiredDate()));

        if ("99991231".equals(DateUtils.dateToStringNoBar(hyDriverDb.getIdcardExpiredDate()))) {
            driverReportDTO.setIdCardDeadline("2099-12-31 23:59:59");
        } else {
            driverReportDTO.setIdCardDeadline(DateUtils.dateTimeToString(hyDriverDb.getIdcardExpiredDate()));
        }

        driverReportDTO.setDrivercardStartline(DateUtils.dateTimeToString(hyDriverDb.getValidPeriodFrom()));

        if ("99991231".equals(DateUtils.dateToStringNoBar(hyDriverDb.getValidPeriodTo()))) {
            driverReportDTO.setDrivercardDeadline("2099-12-31 23:59:59");
        } else {
            driverReportDTO.setDrivercardDeadline(DateUtils.dateTimeToString(hyDriverDb.getValidPeriodTo()));
        }

        driverReportDTO.setIssuingOrganizations(hyDriverDb.getIssuingOrganizations());
        driverReportDTO.setIsIndividual(2);

        HyDriverReport hyDriverReport = new HyDriverReport();
        try {
            String reportResult = this.ordosReportPlatformService.sendReport(OrdosReportConstant.DRIVER_SEND_URL, JSONUtil.toJsonStr(driverReportDTO));
            if (StringUtils.isNotEmpty(reportResult)) {
                R result = JSON.parseObject(reportResult, R.class);
                boolean res = result.getCode() == 200 ? true : false;
                //该信息本年度内修改次数已满，不作为错误信息处理
                if (result.getMsg().contains("修改次数已满")) {
                    res = true;
                }

                hyDriverReport.setDriverId(driverId);
                hyDriverReport.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_ORDOS.getCode());
                hyDriverReport.setDriverUploadStatus(res ? "1" : "2");
                hyDriverReport.setUploadDate( new Date() );
                hyDriverReport.setCompanyId(companyId);
                hyDriverReport.setDriverReportFailureReason(result.getMsg());
                hyDriverReportService.saveDriverReport(hyDriverReport);

                this.driverService.updateZjUploadStatusById(driverId, hyDriverReport.getDriverUploadStatus());
                log.info("鄂尔多斯市监管更新司机上报回执信息, {}, {}", res, result.getMsg());

                return res ? Result.OK("上报成功") : Result.error(result.getMsg());
            } else {
                throw new JeecgBootException("未知异常");
            }
        } catch (Exception e){
            e.printStackTrace();
        }

        return Result.error("司机上报数据异常");
    }

    @Override
    public Result reportVehicle(String vehicleId, String companyId) {

        HyVehicle hyVehicleDb = this.vehicleService.getById(vehicleId);
        if (hyVehicleDb == null) {
            return Result.error("未找到对应数据");
        }

        if (null == hyVehicleDb.getRoadTransportExpiredDate()) {
            return Result.error("请先填写道路运输证有效期");
        }

        if (hyVehicleDb.getRoadTransportExpiredDate().before(new Date())) {
            return Result.error("道路运输证已过期，请确认是否填写正确");
        }

        VehicleReportDTO vehicleReport = new VehicleReportDTO();
        vehicleReport.setPlateNumber(hyVehicleDb.getVehicleNumber());
        vehicleReport.setDrivingLicense(staticUrl + hyVehicleDb.getDrivingLicenseImg());
        vehicleReport.setDrivingLicenseBack(staticUrl + hyVehicleDb.getDrivingLicenseImg2());
        vehicleReport.setDrivingLicenseExpirationDate(DateUtils.dateTimeToString(hyVehicleDb.getRoadTransportExpiredDate()));
        vehicleReport.setDrivingLicenseOrganizations(hyVehicleDb.getIssuingOrganizations());
        vehicleReport.setOwner(hyVehicleDb.getOwner());
        vehicleReport.setPlateNumberColor(hyVehicleDb.getVehiclePlateColorCode());
        vehicleReport.setTransportCode(hyVehicleDb.getRoadTransportNumber());
        vehicleReport.setTransportUrl(staticUrl + hyVehicleDb.getRoadTransportImg());
        vehicleReport.setTradingCardExpirationDate(DateUtils.dateTimeToString(hyVehicleDb.getRoadTransportExpiredDate()));
        vehicleReport.setCurbWeight(BigDecimal.ZERO);
        vehicleReport.setTractionWeight(BigDecimal.ZERO);
        vehicleReport.setApprovalLoadWeight(hyVehicleDb.getVehicleTonnage());
        vehicleReport.setTotalWeight(hyVehicleDb.getGrossMass());
        vehicleReport.setEnergyType(hyVehicleDb.getVehicleEnergyType());

        //报废年限15年
        Date mandatoryScrapDate = DateUtil.offsetMonth(hyVehicleDb.getIssueDate(), 12 * 15);
        vehicleReport.setMandatoryScrapDate(DateUtils.dateTimeToString(mandatoryScrapDate));

        List<HyVehicleType> hyVehicleTypeList = vehicleService.getHyVehicleByPid("1");
        HyVehicleType hyVehicleType = hyVehicleTypeList.stream().filter(s->hyVehicleDb.getVehicleType().contains(s.getText())).findAny().orElse(null);
        if (hyVehicleType == null) {
            throw new JeecgBootException("车辆类型不存在,请修改后重新上报");
        }

        vehicleReport.setModelType(hyVehicleType.getValue());

        HyVehicleReport hyVehicleReport = new HyVehicleReport();
        try {
            String reportResult = this.ordosReportPlatformService.sendReport(OrdosReportConstant.VEHICLE_SEND_URL, JSONUtil.toJsonStr(vehicleReport));
            if(StringUtils.isNotEmpty(reportResult)){
                R result = JSON.parseObject(reportResult, R.class);
                boolean res =  result.getCode() == 200 ?  true : false;
                //该信息本年度内修改次数已满，不作为错误信息处理
                if (result.getMsg().contains("修改次数已满")) {
                    res = true;
                }

                hyVehicleReport.setVehicleId(vehicleId);
                hyVehicleReport.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_ORDOS.getCode());
                hyVehicleReport.setVehicleUploadStatus(res ? "1" : "2");
                hyVehicleReport.setUploadDate(new Date());
                hyVehicleReport.setCompanyId(companyId);
                hyVehicleReport.setVehicleReportFailureReason(result.getMsg());
                vehicleReportService.saveVehicleReport(hyVehicleReport);

                this.vehicleService.updateZjUploadStatusById(vehicleId, hyVehicleReport.getVehicleUploadStatus());
                log.info("鄂尔多斯市监管更新车辆上报回执信息, {}, {}", res, result.getMsg());

                return res ? Result.OK("上报成功") : Result.error(result.getMsg());
            } else {
                throw new JeecgBootException("未知异常");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.error("车辆上报数据异常");
    }


    //上传货主信息
    @Override
    public Result reportCustomer(String customerId, String companyId) {

        HyCustomer hyCustomerDb = this.customerService.getById(customerId);
        HyCustomerCompany customerCompany = this.customerCompanyService.getByCustomerId(hyCustomerDb.getId());
        if (null == hyCustomerDb) {
            return Result.error("未找到对应货主数据");
        }

        if (null == customerCompany) {
            return Result.error("未找到货主签约信息");
        }

        CustomerReportDTO customerReport = new CustomerReportDTO();
        if ("1".equals(hyCustomerDb.getCustomerType())) {

            customerReport.setName(hyCustomerDb.getCustomerName());
            customerReport.setBpnCode(hyCustomerDb.getIdcard());
            customerReport.setBpnImg(staticUrl + hyCustomerDb.getIdcardImg());
            customerReport.setRegistrationTime(DateUtils.dateTimeToString(hyCustomerDb.getIdcardExpiredDate()));

        } else {
            if (null == hyCustomerDb.getClrq()) {
                return Result.error("营业执照注册时间不能为空");
            }

            customerReport.setName(hyCustomerDb.getCustomerName());
            customerReport.setBpnCode(hyCustomerDb.getCreditCode());
            customerReport.setBpnImg(staticUrl + hyCustomerDb.getBusinessLicenseImg());
            customerReport.setRegistrationTime(DateUtils.dateTimeToString(hyCustomerDb.getClrq()));
        }

        String mergerName = hyAreaService.fuzzyFindMergerName(hyCustomerDb.getCountyCode());
        if (StrUtil.isEmpty(mergerName) || mergerName.split(",").length < 3) {
            return Result.error("查询注册地省市县编码失败");
        }

        customerReport.setProvince(mergerName.split(",")[0] + "省");
        customerReport.setCity(mergerName.split(",")[1] + "市");
        customerReport.setArea(mergerName.split(",")[2]);
        customerReport.setAreaCode(hyCustomerDb.getCountyCode());
        customerReport.setAddress(hyCustomerDb.getDetailAddress());
        customerReport.setContacts(hyCustomerDb.getContactName());
        customerReport.setPhone(hyCustomerDb.getLoginPhone());
        customerReport.setContractNumber(customerCompany.getContractNumber());
        customerReport.setContractUrl(staticUrl + customerCompany.getImgContract());
        customerReport.setContractStartDate(DateUtils.dateTimeToString(customerCompany.getExpireStartTime()));
        customerReport.setContractEndDate(DateUtils.dateTimeToString(customerCompany.getExpireEndTime()));

        try {
            String reportResult = this.ordosReportPlatformService.sendReport(OrdosReportConstant.CUSTOMER_SEND_URL, JSONUtil.toJsonStr(customerReport));
            if(StringUtils.isNotEmpty(reportResult)){
                R result = JSON.parseObject(reportResult, R.class);
                boolean res = result.getCode() == 200 ? true : false;
                //该信息本年度内修改次数已满，不作为错误信息处理
                if (result.getMsg().contains("修改次数已满")) {
                    res = true;
                }

                this.customerService.update(new LambdaUpdateWrapper<HyCustomer>()
                        .eq(HyCustomer::getId, customerId)
                        .set(HyCustomer::getTosUploadStatus, res ? "1" : "2")
                        .set(HyCustomer::getTosUploadTime, new Date())
                );
                log.info("鄂尔多斯市监管更新货主上报回执信息, {}, {}", res, result.getMsg());

                return res ? Result.OK("上报成功") : Result.error(result.getMsg());
            } else {
                throw new JeecgBootException("未知异常");
            }

        } catch (Exception e) {
            e.printStackTrace();
            this.customerService.update(new LambdaUpdateWrapper<HyCustomer>()
                    .eq(HyCustomer::getId, customerId)
                    .set(HyCustomer::getTosUploadStatus, "2")
                    .set(HyCustomer::getTosUploadTime, new Date())
            );
        }

        return Result.error("货主数据上报异常");
    }


    /**
     * 鄂尔多斯监管
     *
     * @param hyShippingNote
     * @return
     */
    @Override
    public Result reportShippingNote(HyShippingNote hyShippingNote, String shippingStatus, String lng, String lat) {

        if (null == hyShippingNote) {
            return Result.error("市监管上报失败: 未找到对应运单数据");
        }

        if (shippingStatus.equals(ShippingStatus.运输中.getValue())) {
            log.info("开始上报运单装货数据, {}", JSONUtil.toJsonStr(hyShippingNote));
            return uploadShippingLoading(hyShippingNote, lng, lat);
        }

        if (shippingStatus.equals(ShippingStatus.已交货.getValue())) {
            log.info("开始上报运单卸货数据");
            return uploadShippingUnLoading(hyShippingNote, lng, lat);
        }

        if (shippingStatus.equals("10")) {
            log.info("开始上报运单轨迹数据, {}", hyShippingNote.getShippingNoteNumber());
            return uploadShippingTrace(hyShippingNote);
        }

        if (shippingStatus.equals("20")) {
            log.info("开始上报结算信息, {}", hyShippingNote.getShippingNoteNumber());
            return uploadPayment(hyShippingNote);
        }

        if (shippingStatus.equals("30")) {
            log.info("开始上报资金流水， {}", hyShippingNote.getShippingNoteNumber());
            return uploadCapitalFlow(hyShippingNote);
        }

        if (shippingStatus.equals("40")) {
            log.info("开始上报开票信息, {}", hyShippingNote.getShippingNoteNumber());
            return uploadInvoicing(hyShippingNote);
        }

        return Result.error("上报数据传输失败");
    }


    private Result uploadShippingLoading(HyShippingNote hyShippingNote, String lng, String lat) {

        HyCustomer hyCustomer = customerService.getById(hyShippingNote.getCustomerId());
        if (hyCustomer == null) {
            return Result.error("市监管上报失败: 该运单货主信息不能为空");
        }

        HyCustomerCompany hyCustomerCompany = this.customerCompanyService.getByCustomerId(hyCustomer.getId());
        if (hyCustomerCompany == null) {
            return Result.error("市监管上报失败: 签约信息不能为空");
        }

        HyOrder hyOrder = orderService.getById(hyShippingNote.getOrderId());
        if (hyOrder == null) {
            return Result.error("市监管上报失败: 该运单货源信息不能为空");
        }

        HyDriver hyDriver = driverService.getById(hyShippingNote.getDriverId());
        if (hyDriver == null) {
            return Result.error("市监管上报失败: 该运单司机信息不能为空");
        }

        HyVehicle hyVehicle = vehicleService.getById(hyShippingNote.getVehicleId());
        if (hyVehicle == null) {
            return Result.error("市监管上报失败: 该运单车辆信息不能为空");
        }

        HyCompany hyCompany = companyService.getById(hyShippingNote.getCompanyId());
        if (hyCompany == null) {
            return Result.error("市监管上报失败: 该运单公司信息不能为空");
        }

        LoadingReportDTO loadingReport = new LoadingReportDTO();
        loadingReport.setShipmentCode(hyShippingNote.getShippingNoteNumber());
        loadingReport.setReceiverEnterprise(hyOrder.getReceiveContactName());
        loadingReport.setReceiverEnterpriseCode(hyOrder.getReceiveContactCredit());
        loadingReport.setConsignorName(hyCustomer.getCustomerName());
        loadingReport.setConsignorCode(hyCustomer.getCreditCode());
        loadingReport.setCarrierPlatform(hyCompany.getCompanyName());

        if (null == hyOrder.getSendLongitude() || null == hyOrder.getSendLatitude()) {
            return Result.error("市监管上报失败: 发货地址经纬度定位失败");
        }

        String mergerName = this.areaService.fuzzyFindMergerName(hyOrder.getSendAreaCode());
        if (StrUtil.isEmpty(mergerName) || mergerName.split(",").length < 3) {
            return Result.error("市监管上报失败: 行政区划代码查询失败");
        } else {
            loadingReport.setLoadingProvinceName(mergerName.split(",")[0] + "省");
            loadingReport.setLoadingCityName(mergerName.split(",")[1] + "市");
            loadingReport.setLoadingAreaName(mergerName.split(",")[2]);
            loadingReport.setLoadingAreaAddress(hyOrder.getSendAddress());
            loadingReport.setLoadingAreaCode(hyOrder.getSendAreaCode());
            loadingReport.setLoadingLon(hyOrder.getSendLongitude().toString());
            loadingReport.setLoadingLat(hyOrder.getSendLatitude().toString());
        }

        String mergerName2 = this.areaService.fuzzyFindMergerName(hyOrder.getReceiveAreaCode());
        if (StrUtil.isEmpty(mergerName2) || mergerName2.split(",").length < 3) {
            return Result.error("市监管上报失败: 行政区划代码查询失败");
        } else {
            loadingReport.setUnloadingProvinceName(mergerName2.split(",")[0] + "省");
            loadingReport.setUnloadingCityName(mergerName2.split(",")[1] + "市");
            loadingReport.setUnloadingAreaName(mergerName2.split(",")[2]);
            loadingReport.setUnloadingAreaAddress(hyOrder.getReceiveAddress());
            loadingReport.setUnloadingAreaCode(hyOrder.getReceiveAreaCode());
            loadingReport.setUnloadingLon(hyOrder.getReceiveLongitude().toString());
            loadingReport.setUnloadingLat(hyOrder.getReceiveLatitude().toString());
        }

        loadingReport.setGoodsName(hyOrder.getDescriptionOfGoods());
        loadingReport.setGoodsNorms(1);
        loadingReport.setGoodsType(hyOrder.getCargoTypeClassificationCode());

        RegeoDTO regeoDTO = this.amapService.coordinateRegeo(lng, lat);
        if (null == regeoDTO || StrUtil.isEmpty(regeoDTO.getAreaCode())) {
            return Result.error("市监管上报失败: 获取司机当前装货经纬度信息失败");
        }
        log.info("司机装货{}", JSONUtil.toJsonStr(regeoDTO));
        loadingReport.setLoadingSignLocationProvince(regeoDTO.getProvince());
        loadingReport.setLoadingSignLocationCity(regeoDTO.getCity());
        loadingReport.setLoadingSignLocationArea(regeoDTO.getDistrict());
        loadingReport.setLoadingSignLocation(regeoDTO.getAddress());
        loadingReport.setLoadingSignLocationCode(regeoDTO.getAreaCode());
        loadingReport.setLoadingSignLocationLon(lng);
        loadingReport.setLoadingSignLocationLat(lat);
        loadingReport.setLoadTareTime(DateUtils.dateTimeToString(hyShippingNote.getStatusDtLoading()));
        loadingReport.setLoadImg(staticUrl + hyShippingNote.getImgLoading().split(",")[0]);
        loadingReport.setInsuranceCompany("none");
        loadingReport.setPolicyNo("none");
        loadingReport.setWaybillCreateTime(DateUtils.dateTimeToString(hyShippingNote.getCreateTime()));

        loadingReport.setShipperContractNumber(hyCustomerCompany.getContractNumber());
        loadingReport.setContractNumber(hyShippingNote.getContractNum());
        loadingReport.setContractUrl(staticUrl + hyShippingNote.getShippingContract());
        loadingReport.setLoadingWeight(hyShippingNote.getGoodsWeightLoading());

        loadingReport.setDriverName(hyDriver.getDriverName());
        loadingReport.setDriverCardId(hyDriver.getIdcard());
        loadingReport.setDriverPhone(hyDriver.getTelephone());
        loadingReport.setLicenseNumber(hyVehicle.getVehicleNumber());

        try {
            String reportResult = this.ordosReportPlatformService.sendReport(OrdosReportConstant.LOADING_SEND_URL, JSONUtil.toJsonStr(loadingReport));
            if (StringUtils.isNotEmpty(reportResult)) {
                R result = JSON.parseObject(reportResult, R.class);
                boolean res = result.getCode() == 200 ? true : false;
                return res ? Result.OK("上报完成") : Result.error(result.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.error("上报数据过程中发生错误");
    }

    private Result uploadShippingUnLoading(HyShippingNote hyShippingNote, String lng, String lat) {

        UnloadingReportDTO unloadingReport = new UnloadingReportDTO();
        unloadingReport.setShipmentCode(hyShippingNote.getShippingNoteNumber());

        RegeoDTO regeoDTO = this.amapService.coordinateRegeo(lng, lat);
        if (null == regeoDTO || StrUtil.isEmpty(regeoDTO.getAreaCode())) {
            return Result.error("市监管上报失败: 获取司机当前卸货经纬度信息失败");
        }
        log.info("司机卸货{}", JSONUtil.toJsonStr(regeoDTO));
        unloadingReport.setUnloadingSignLocationProvince(regeoDTO.getProvince());
        unloadingReport.setUnloadingSignLocationCity(regeoDTO.getCity());
        unloadingReport.setUnloadingSignLocationArea(regeoDTO.getDistrict());
        unloadingReport.setUnloadingSignLocation(regeoDTO.getAddress());
        unloadingReport.setUnloadingSignLocationCode(regeoDTO.getAreaCode());
        unloadingReport.setUnloadingSignLocationLon(lng);
        unloadingReport.setUnloadingSignLocationLat(lat);
        unloadingReport.setUnloadTareTime(DateUtils.dateTimeToString(hyShippingNote.getStatusDtUnloading()));
        unloadingReport.setUnloadImg(staticUrl + hyShippingNote.getImgUnloading().split(",")[0]);
        unloadingReport.setUnloadingWeight(hyShippingNote.getGoodsWeightUnloading());

        try {
            String reportResult = this.ordosReportPlatformService.sendReport(OrdosReportConstant.UNLOADING_SEND_URL, JSONUtil.toJsonStr(unloadingReport));
            if (StringUtils.isNotEmpty(reportResult)) {
                R result = JSON.parseObject(reportResult, R.class);
                boolean res = result.getCode() == 200 ? true : false;
                return res ? Result.OK("上报完成") : Result.error(result.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.error("上报数据过程中发生错误");
    }


    private Result uploadShippingTrace(HyShippingNote hyShippingNote) {

        if (!hyShippingNote.getShippingStatus().equals(ShippingStatus.已签收.getValue())) {
            return Result.error("该运单不是已签收状态，请确认运单状态");
        }

        HyVehicle hyVehicle = this.vehicleService.getById(hyShippingNote.getVehicleId());

        //轨迹
        List<TracesDTO> tracesInfoDTOS;
        String vehicleTrackSwitch = this.settingService.getSettingValueByTag2("vehicle_track_switch");
        if ("1".equals(vehicleTrackSwitch)) {
            tracesInfoDTOS = getTracesList(hyVehicle, hyShippingNote);
            if (CollectionUtils.isEmpty(tracesInfoDTOS)) {
                return Result.error("该运单轨迹信息不存在");
            }
        } else {
            //如果开启模拟轨迹
            tracesInfoDTOS = getSimulateTracesList(hyShippingNote);
        }

        TraceReportDTO traceReportDTO = new TraceReportDTO();
        traceReportDTO.setShipmentCode(hyShippingNote.getShippingNoteNumber());
        traceReportDTO.setLocationJson(tracesInfoDTOS);

        try {
            String reportResult = this.ordosReportPlatformService.sendReport(OrdosReportConstant.TRACE_SEND_URL, JSONUtil.toJsonStr(traceReportDTO));
            if (StringUtils.isNotEmpty(reportResult)) {
                R result = JSON.parseObject(reportResult, R.class);
                boolean res = result.getCode() == 200 ? true : false;
                return res ? Result.OK("上报完成") : Result.error(result.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("上报鄂尔多斯监管轨迹失败, {}", e.getMessage());
        }

        return Result.error("上报鄂尔多斯市监管轨迹数据发生错误");
    }


    private Result uploadPayment(HyShippingNote hyShippingNote) {

        if (!hyShippingNote.getShippingPayStatus().equals(ShippingPayStatus.支付完成.getValue())) {
            return Result.error("该运单未支付完成,请先进行运单支付");
        }

        HyOrdosReport hyOrdosReport = this.hyOrdersReportService.getByShippingNoteNumber(hyShippingNote.getShippingNoteNumber());
        if (null == hyOrdosReport) {
            return Result.error("未找到该运单装卸货上报记录");
        }
        if (!"1".equals(hyOrdosReport.getTraceReportStatus())) {
            return Result.error("运单轨迹上报未完成，请先上报轨迹数据");
        }

        HyDriver hyDriver = driverService.getById(hyShippingNote.getDriverId());
        if (hyDriver == null) {
            return Result.error("该运单司机信息不能为空");
        }

        HyDriverBank driverSelfBank = driverBankService.getDriverSelfBank(hyDriver.getId());
        if (null == driverSelfBank) {
            return Result.error("未找到司机银行卡信息");
        }

        PaymentDTO paymentDTO = new PaymentDTO();
        paymentDTO.setShipmentCode(hyShippingNote.getShippingNoteNumber());
        paymentDTO.setFreight(hyShippingNote.getDriverFee());
        paymentDTO.setTotalDriverFreight(hyShippingNote.getDriverFee());
        paymentDTO.setTotalFreight(hyShippingNote.getCustomerFee());
        paymentDTO.setGoodsSettlementWeight(hyShippingNote.getGoodsWeightUnloading());
        paymentDTO.setBankCardNo(driverSelfBank.getBankNum());
        paymentDTO.setBankCardHolderName(hyDriver.getDriverName());
        paymentDTO.setBankCardHolderiDcardNo(hyDriver.getIdcard());

        try {
            String reportResult = this.ordosReportPlatformService.sendReport(OrdosReportConstant.PAYMENT_SEND_URL, JSONUtil.toJsonStr(paymentDTO));
            if (StringUtils.isNotEmpty(reportResult)) {
                R result = JSON.parseObject(reportResult, R.class);
                boolean res = result.getCode() == 200 ? true : false;
                return res ? Result.OK("上报完成") : Result.error(result.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("上报鄂尔多斯监管运单失败, {}", e.getMessage());
        }

        return Result.error("上报鄂尔多斯市监管运单数据发生错误");
    }


    private Result uploadCapitalFlow(HyShippingNote hyShippingNote) {

        if (!hyShippingNote.getShippingPayStatus().equals(ShippingPayStatus.支付完成.getValue())) {
            return Result.error("该运单未支付完成,请先进行运单支付");
        }

        HyOrdosReport hyOrdosReport = this.hyOrdersReportService.getByShippingNoteNumber(hyShippingNote.getShippingNoteNumber());
        if (null == hyOrdosReport) {
            return Result.error("未找到该运单装卸货上报记录");
        }
        if (!"1".equals(hyOrdosReport.getTraceReportStatus())) {
            return Result.error("运单轨迹上报未完成，请先上报轨迹数据");
        }

        HyDriver hyDriver = driverService.getById(hyShippingNote.getDriverId());
        if (hyDriver == null) {
            return Result.error("该运单司机信息不能为空");
        }

        HyDriverBank driverSelfBank = driverBankService.getDriverSelfBank(hyDriver.getId());
        if (null == driverSelfBank) {
            return Result.error("未找到司机银行卡信息");
        }

        HyShippingNoteBill hyShippingNoteBill = this.hyShippingNoteBillService.getBillByShippingId(hyShippingNote.getId());

        String bankHdImg = StrUtil.isNotEmpty(hyShippingNoteBill.getBankHd()) ?
                bankpath + File.separator + hyShippingNoteBill.getBankHd() :
                uploadpath + File.separator + hyShippingNoteBill.getBankHdImg();
        if (StrUtil.isEmpty(bankHdImg)) {
            return Result.error("未找到银行回单文件数据");
        }

        CapitalFlowReportDTO capitalFlowReport = new CapitalFlowReportDTO();
        capitalFlowReport.setShipmentCode(hyShippingNote.getShippingNoteNumber());
        capitalFlowReport.setSequenceCode(hyShippingNoteBill.getBillNum());
        capitalFlowReport.setPayeeName(hyShippingNoteBill.getCarrier());
        capitalFlowReport.setPayeeCode(hyDriver.getIdcard());
        capitalFlowReport.setPayeeBankCode("1".equals(hyShippingNoteBill.getBillImportFlag()) ?
                hyShippingNoteBill.getCraccno() :
                hyShippingNoteBill.getCraccno()+hyShippingNoteBill.getCrlogaccno());
        capitalFlowReport.setBankCode(hyShippingNoteBill.getBankCode());
        capitalFlowReport.setAmount(hyShippingNoteBill.getAmt().setScale(3, BigDecimal.ROUND_DOWN));
        capitalFlowReport.setPayDate(DateUtils.dateToStringDateTime(hyShippingNoteBill.getPayDt()));
        capitalFlowReport.setPayer(hyShippingNoteBill.getDbaccname());
        capitalFlowReport.setVoucherUrl(staticUrl + bankHdImg);

        try {
            String reportResult = this.ordosReportPlatformService.sendReport(OrdosReportConstant.CAPITALFLOW_SEND_URL, JSONUtil.toJsonStr(capitalFlowReport));
            if (StringUtils.isNotEmpty(reportResult)) {
                R result = JSON.parseObject(reportResult, R.class);
                boolean res = result.getCode() == 200 ? true : false;
                return res ? Result.OK("上报完成") : Result.error(result.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("上报鄂尔多斯监管资金流水失败, {}", e.getMessage());
        }

        return Result.error("上报鄂尔多斯市监管资金流水数据发生错误");
    }


    private Result uploadInvoicing(HyShippingNote hyShippingNote) {

        if (!hyShippingNote.getShippingPayStatus().equals(ShippingPayStatus.支付完成.getValue())) {
            return Result.error("该运单未支付完成,请先进行运单支付");
        }

        HyOrdosReport hyOrdosReport = this.hyOrdersReportService.getByShippingNoteNumber(hyShippingNote.getShippingNoteNumber());
        if (null == hyOrdosReport) {
            return Result.error("未找到该运单装卸货上报记录");
        }
        if (!"1".equals(hyOrdosReport.getPayReportStatus())) {
            return Result.error("资金流水上报未完成，请先上报资金流水");
        }

        HyInvoice hyInvoice = this.hyInvoiceService.getOne(new LambdaQueryWrapper<HyInvoice>().like(HyInvoice::getShippingIds, hyShippingNote.getId()));
        if (null == hyInvoice) {
            return Result.error("未找到该运单的开票记录");
        }

        InvoiceReportDTO invoiceReportDTO = new InvoiceReportDTO();
        invoiceReportDTO.setShipmentCode(hyShippingNote.getShippingNoteNumber());
        invoiceReportDTO.setBillCode(hyInvoice.getInvoiceCode());
        invoiceReportDTO.setBillNumber(hyInvoice.getInvoiceHm());
        invoiceReportDTO.setBillDate(DateUtils.dateTimeToString(hyInvoice.getInvoiceDt()));
        if (StrUtil.isNotEmpty(hyInvoice.getImg())) {
            invoiceReportDTO.setBillUrl(staticUrl + hyInvoice.getImg());
        }

        try {
            String reportResult = this.ordosReportPlatformService.sendReport(OrdosReportConstant.INVOICE_SEND_URL, JSONUtil.toJsonStr(invoiceReportDTO));
            if (StringUtils.isNotEmpty(reportResult)) {
                R result = JSON.parseObject(reportResult, R.class);
                boolean res = result.getCode() == 200 ? true : false;
                return res ? Result.OK("上报完成") : Result.error(result.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("上报鄂尔多斯监管开票信息失败, {}", e.getMessage());
        }

        return Result.error("上报鄂尔多斯市监管开票信息发生错误");
    }

    private List<TracesDTO> getSimulateTracesList(HyShippingNote hyShippingNote) {
        List<TracesDTO> gpsDTOS = new ArrayList<>();
        List<GpsDTO> gpsDTOList = this.amapService.getMapGps(hyShippingNote);

        if (CollUtil.isEmpty(gpsDTOList)) {
            log.info("获取模拟轨迹，当前运单{}无轨迹点数", hyShippingNote.getShippingNoteNumber());
            return gpsDTOS;
        }

        log.info("获取模拟轨迹，当前运单{} 轨迹点数{}", hyShippingNote.getShippingNoteNumber(), gpsDTOList.size());
        int a = gpsDTOList.size();
        if (a <= 1000) {
            for (GpsDTO dto : gpsDTOList) {
                TracesDTO gpsDTO = new TracesDTO();
                double[] coordinate = LngLonUtil.gcj02_To_Bd09(Double.valueOf(dto.getLat()), Double.valueOf(dto.getLon()));
                gpsDTO.setLon(new BigDecimal(coordinate[1]).setScale(5, RoundingMode.DOWN).toString());
                gpsDTO.setLat(new BigDecimal(coordinate[0]).setScale(5, RoundingMode.DOWN).toString());
                gpsDTO.setTime(
                        DateUtils.dateTimeToStringT(DateUtils.stringToDateTime(dto.getPositionTime())));
                gpsDTOS.add(gpsDTO);
            }
        } else {
            int b = getFrequency(a);
            int n = 1;
            for (GpsDTO dto : gpsDTOList) {
                if (n % b == 0) {
                    TracesDTO gpsDTO = new TracesDTO();
                    double[] coordinate = LngLonUtil.gcj02_To_Bd09(Double.valueOf(dto.getLat()), Double.valueOf(dto.getLon()));
                    gpsDTO.setLon(new BigDecimal(coordinate[1]).setScale(5, RoundingMode.DOWN).toString());
                    gpsDTO.setLat(new BigDecimal(coordinate[0]).setScale(5, RoundingMode.DOWN).toString());
                    gpsDTO.setTime(DateUtils.dateTimeToStringT(DateUtils.stringToDateTime(dto.getPositionTime())));
                    gpsDTOS.add(gpsDTO);
                }
                n++;
            }
        }

        return gpsDTOS;
    }

    /**
     * 陆交开放平台  同步运单的车辆轨迹数据
     *
     * @param hyVehicle
     * @param hyShippingNote
     * @return
     */
    private List<TracesDTO> getTracesList(HyVehicle hyVehicle, HyShippingNote hyShippingNote) {
        List<TracesDTO> gpsDTOS = new ArrayList<>();
        String startTime = DateUtils.dateTimeToString(hyShippingNote.getStatusDtLoading());
        String endTime = DateUtils.dateTimeToString(hyShippingNote.getStatusDtUnloading());
        //如果超出了收发货时间，税务系统会自动抛弃，所以用new date不会有问题
        if (StrUtil.isEmpty(endTime)) {
            endTime = DateUtils.dateTimeToString(new Date());
        }
        String vehicleColor = StringUtils.isNotEmpty(hyVehicle.getVehiclePlateColorCode()) ? hyVehicle.getVehiclePlateColorCode() : "2";
        WaybillRouteVO waybillRouteVO = waybillRouteService.getWaybillRoute(hyVehicle.getVehicleNumber(), vehicleColor, startTime, endTime, "BD09");
        if (waybillRouteVO != null && CollectionUtils.isNotEmpty(waybillRouteVO.getPointDataList())) {
            List<PointDataListVO> pointDataListVOS = waybillRouteVO.getPointDataList();
            int a = pointDataListVOS.size();

            if (a <= 1000) {
                for (PointDataListVO pointDataListVO : pointDataListVOS) {
                    TracesDTO gpsDTO = new TracesDTO();
                    double[] coordinate = LngLonUtil.gcj02_To_Bd09(Double.valueOf(pointDataListVO.getLat()), Double.valueOf(pointDataListVO.getLng()));

                    gpsDTO.setLon(new BigDecimal(coordinate[1]).toString());
                    gpsDTO.setLat(new BigDecimal(coordinate[0]).toString());
                    //gpsDTO.setLatitude(new BigDecimal(pointDataListVO.getLat()).setScale(6, BigDecimal.ROUND_DOWN));
                    gpsDTO.setTime(
                            DateUtils.dateTimeToStringT(DateUtils.stringToDateTime(pointDataListVO.getReceiveTime())));
                    gpsDTOS.add(gpsDTO);
                }
            } else {
                int b = getFrequency(a);
                int n = 1;
                for (PointDataListVO pointDataListVO : pointDataListVOS) {
                    if (n % b == 0) {
                        TracesDTO gpsDTO = new TracesDTO();
                        double[] coordinate = LngLonUtil.gcj02_To_Bd09(Double.valueOf(pointDataListVO.getLat()), Double.valueOf(pointDataListVO.getLng()));
                        gpsDTO.setLon(new BigDecimal(coordinate[1]).toString());
                        gpsDTO.setLat(new BigDecimal(coordinate[0]).toString());
//                        gpsDTO.setLongitude(new BigDecimal(pointDataListVO.getLng()));
//                        gpsDTO.setLatitude(new BigDecimal(pointDataListVO.getLat()));
                        gpsDTO.setTime(DateUtils.dateTimeToStringT(DateUtils.stringToDateTime(pointDataListVO.getReceiveTime())));
                        gpsDTOS.add(gpsDTO);
                    }
                    n++;
                }
            }

        }
        return gpsDTOS;
    }

    /**
     * 获取频次
     *
     * @param a
     * @return
     */
    private int getFrequency(Integer a) {
        int b = 1;
        if (a > 1000 && a <= 2000) {
            b = 10;
        } else if (a > 2000 && a <= 3000) {
            b = 20;
        } else if (a > 3000 && a <= 4000) {
            b = 30;
        } else if (a > 4000 && a <= 5000) {
            b = 40;
        } else if (a > 5000 && a <= 6000) {
            b = 50;
        } else {
            b = 60;
        }
        return b;
    }

}
